#pragma once

#include <boostext/iostreams/bin_iostream.hpp>

#include <engine.script/Function.hpp>
#include <engine.script/Reflectable.hpp>

#include "exports.hpp"




namespace Engine
{
	namespace Debugger
	{
		/**
		 * This structure has the purpose to store an angelscript callstack, as well as to
		 * serialize it to a stream / from a stream.
		 *
		 * This structure merely stores the function ids of a given callstack (ie. a vector of functions).
		 * It's easier to serialize those instead of a complex structure like a Script::Function.
		 */
		class ENGINE_DEBUGGER_API Callstack
		{
		public:

			/**
			 * Creates an empty Callstack.
			 * Mainly used to deserialize the Callstack from a stream.
			 */
			Callstack();

			/**
			 * Create a callstack with the given functions.
			 */
			Callstack(const std::vector<Script::Function>& stack);

			/**
			 * Create a callstack with the given function, defined by [first, last).
			 */
			template <typename Iter>
			Callstack(Iter first, Iter last)
			{
				m_stack.reserve(stack.size());
				for(auto i = stack.begin(); i != stack.end(); ++i)
					m_stack.push_back(i->id());
			}



			/**
			 * @returns   a vector with the actual functions
			 * @throws    when there is no function with any of the stored ids
			 *
			 * This function tries to create a vector of functions, aequivalent to those it has originally been created
			 * (or restored) with.
			 * It is especially usefull when sending the bytecode of a module to another process (for example from the
			 * daemon to the controller) and then merely sending the sequence of function ids as the callstack.
			 * It will not work when both engines are not in the same state (for example when they have not registred the same types).
			 */
			std::vector<Script::Function> functions(Script::Reflectable::ptr reflectable) const;



			friend ENGINE_DEBUGGER_API boostext::iostreams::bin_ostream& operator<<(boostext::iostreams::bin_ostream& stream, const Callstack& callstack);
			friend ENGINE_DEBUGGER_API boostext::iostreams::bin_istream& operator>>(boostext::iostreams::bin_istream& stream, Callstack& callstack);

		private:

			Script::Reflectable::weak_ptr   m_reflectable;

			/// Contains all functions of the callstack: The first function is the entry point
			/// and the last defines the topmost functions
			std::vector<int>   m_stack;
		};
		///////////////////////////////////////////////////////////////////////////////////////////

		/**
		 * Stores this callstack in the given stream.
		 */
		ENGINE_DEBUGGER_API boostext::iostreams::bin_ostream& operator<<(boostext::iostreams::bin_ostream& stream, const Callstack& callstack);

		/**
		 * Restores this callstack from the given stream.
		 */
		ENGINE_DEBUGGER_API boostext::iostreams::bin_istream& operator>>(boostext::iostreams::bin_istream& stream, Callstack& callstack);
	}
	///////////////////////////////////////////////////////////////////////////////////////////////
}
///////////////////////////////////////////////////////////////////////////////////////////////////
